home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 1 / BBS in a box - Trilogy I.iso / Files / Publish / Photoshop / Plug-in Modules / Code / DialogUtilities.c next >
Encoding:
C/C++ Source or Header  |  1993-04-28  |  14.0 KB  |  780 lines  |  [TEXT/MPS ]

  1. /*
  2.     File: DialogUtilities.c
  3.  
  4.     Copyright 1993 by Adobe Systems, Inc.
  5.  
  6.     C source file for plug-in dialog utilities.
  7. */
  8.  
  9. #include <Dialogs.h>
  10. #include <GestaltEqu.h>
  11. #include <QuickDraw.h>
  12. #include <Types.h>
  13.  
  14. #include "DialogUtilities.h"
  15.  
  16. #include "PITypes.h"
  17. #include "PIGeneral.h"
  18.  
  19. /*****************************************************************************/
  20.  
  21. typedef struct QDVars
  22.     {
  23.     char privates[76];
  24.     long randSeed;
  25.     BitMap screenBits;
  26.     Cursor arrow;
  27.     Pattern dkGray;
  28.     Pattern ltGray;
  29.     Pattern gray;
  30.     Pattern black;
  31.     Pattern white;
  32.     GrafPtr thePort;
  33.     } QDVars;
  34.  
  35. /*****************************************************************************/
  36.  
  37. /* The following routine locates the QuickDraw globals. */
  38.  
  39. static QDVars *GetQDVars (void)
  40.     {
  41.     
  42.     return (QDVars *) ((* (char **) SetCurrentA5 ()) -
  43.                                     (sizeof (QDVars) - sizeof (GrafPtr)));
  44.     
  45.     }
  46.  
  47. /*****************************************************************************/
  48.  
  49. /* Set the cursor to the arrow cursor. */
  50.  
  51. void SetArrowCursor ()
  52.     {
  53.     
  54.     QDVars *qd = GetQDVars ();
  55.     
  56.     SetCursor (&(qd->arrow));
  57.     
  58.     }
  59.  
  60. /*****************************************************************************/
  61.  
  62. /* Centers a dialog template 1/3 of the way down on the main screen. */
  63.  
  64. void CenterDialog (DialogTHndl dt)
  65.     {
  66.  
  67.     #define menuHeight 20
  68.  
  69.     Rect r;
  70.     short width;
  71.     short height;
  72.     
  73.     QDVars *qd = GetQDVars ();
  74.     
  75.     width  = qd->screenBits.bounds.right;
  76.     height = qd->screenBits.bounds.bottom;
  77.  
  78.     r = (**dt).boundsRect;
  79.     OffsetRect (&r, -r.left, -r.top);
  80.     OffsetRect (&r, (width - r.right) / 2,
  81.                     (height - r.bottom - menuHeight) / 3 + menuHeight);
  82.     (**dt).boundsRect = r;
  83.  
  84.     #undef menuHeight
  85.  
  86.     }
  87.  
  88. /*****************************************************************************/
  89.  
  90. /* Test for Adobe Moveable Modal Dialog if running System 6 */
  91.  
  92. void SetUpMoveableModal (DialogTHndl dt, OSType hostSig)
  93.     {
  94.  
  95.     long    response;
  96.     
  97.     if (Gestalt (gestaltSystemVersion, &response) != noErr)
  98.         response = 0;
  99.         
  100.     if (response < 0x0700)
  101.         {    /* Prior to System 7... */
  102.  
  103.         Handle    windRes = nil;
  104.         
  105.         /* We don't have to release the resource, because opening the
  106.            dialog will do the right thing with it if it exists. */
  107.  
  108.         if (hostSig == '8BIM')
  109.             windRes = GetResource ('WDEF', PSmovableDBoxProc/16);
  110.             
  111.         if (windRes != NULL)
  112.             (*dt)->procID = PSmovableDBoxProc;
  113.         else
  114.             (*dt)->procID = dBoxProc;        /* not moveable, sorry */
  115.  
  116.         }
  117.         
  118.     }
  119.  
  120. /*****************************************************************************/
  121.  
  122. typedef struct ModalData
  123.     {
  124.     
  125.     long oldRefCon;
  126.     
  127.     ModalFilterProcPtr filter;
  128.     
  129.     ProcessEventProc processEvent;
  130.     
  131.     } ModalData;
  132.  
  133. /*****************************************************************************/
  134.  
  135. /* Some handy ASCII values for keystrokes */
  136.  
  137. #define RETURN    0x0D
  138. #define ENTER    0x03
  139. #define PERIOD    '.'
  140. #define ESCAPE    0x1B
  141.  
  142. /*****************************************************************************/
  143.  
  144. /* Event filter to allow movable modal dialogs. */
  145.  
  146. static pascal Boolean DialogFilter (DialogPtr dp,
  147.                                     EventRecord *event,
  148.                                     short *item)
  149.     {
  150.  
  151.     Boolean result = FALSE;
  152.     
  153.     ModalData *data = (ModalData *) GetWRefCon (dp);
  154.     
  155.     if (data->filter)
  156.         {
  157.         
  158.         SetWRefCon (dp, data->oldRefCon);
  159.         
  160.         result = (*data->filter) (dp, event, item);
  161.         
  162.         data->oldRefCon = GetWRefCon (dp);
  163.         
  164.         SetWRefCon (dp, (long) data);
  165.         
  166.         if (result)
  167.             return TRUE;
  168.         
  169.         }
  170.     
  171.     if (event->what == mouseDown)
  172.         {
  173.  
  174.         /* We have to do window-dragging ourselves */
  175.  
  176.         Point pt = event->where;
  177.         WindowPtr window;
  178.  
  179.         if (FindWindow (pt, &window) == inDrag && window == dp)
  180.             {
  181.  
  182.             Rect bounds = (*GetGrayRgn())->rgnBBox;
  183.  
  184.             InsetRect (&bounds, 4, 4);
  185.  
  186.             DragWindow (window, pt, &bounds);
  187.  
  188.             event->what = nullEvent;
  189.  
  190.             }
  191.  
  192.         }
  193.  
  194.     else if (event->what == keyDown)
  195.  
  196.         {
  197.  
  198.         /* We have to do button key-equivalents ourselves, now, too */
  199.  
  200.         char ch = event->message & charCodeMask;
  201.  
  202.         if (ch == RETURN || ch == ENTER)
  203.             {
  204.  
  205.             *item = ok;
  206.  
  207.             FlashDialogButton (dp, ok);
  208.  
  209.             result = TRUE;
  210.  
  211.             }
  212.  
  213.         else if (ch == ESCAPE || (ch == PERIOD && (event->modifiers & cmdKey)))
  214.             {
  215.  
  216.             *item = cancel;
  217.  
  218.             FlashDialogButton (dp, cancel);
  219.  
  220.             result = TRUE;
  221.  
  222.             }
  223.  
  224.         }
  225.  
  226.     else if (event->what == updateEvt || event->what == activateEvt)
  227.         {
  228.  
  229.         /* Pass updates and activates out to the host */
  230.  
  231.         if (data->processEvent && (event->message != ((long) dp)))
  232.             (*data->processEvent) (event);
  233.  
  234.         }
  235.  
  236.     else if (event->what == nullEvent)
  237.         {
  238.  
  239.         /* Let the host idle */
  240.  
  241.         if (data->processEvent)
  242.             (*data->processEvent) (event);
  243.  
  244.         }
  245.  
  246.     return result;
  247.  
  248.     }
  249.  
  250. /*****************************************************************************/
  251.  
  252. void MoveableModalDialog (DialogPtr dp,
  253.                           ProcessEventProc processEvent,
  254.                           ModalFilterProcPtr filter,
  255.                           short *item)
  256.     {
  257.     
  258.     ModalData data;
  259.     
  260.     data.oldRefCon = GetWRefCon (dp);
  261.     data.filter = filter;
  262.     data.processEvent = processEvent;
  263.     
  264.     SetWRefCon (dp, (long) &data);
  265.     
  266.     ModalDialog (&DialogFilter, item);
  267.     
  268.     SetWRefCon (dp, data.oldRefCon);
  269.     
  270.     }
  271.  
  272. /*****************************************************************************/
  273.  
  274. short ShowAlert (short alertID)
  275.     {
  276.     
  277.     Handle alertHandle;
  278.     short result;
  279.     
  280.     alertHandle = GetResource ('ALRT', alertID);
  281.     HNoPurge (alertHandle);
  282.     
  283.     CenterDialog ((DialogTHndl) alertHandle);
  284.     
  285.     result = Alert (alertID, nil);
  286.     
  287.     HPurge (alertHandle);
  288.  
  289.     return result;
  290.     
  291.     }
  292.  
  293. /*****************************************************************************/
  294.  
  295. void ShowAbout (short dialogID)
  296.     {
  297.  
  298.     short item;
  299.     DialogPtr dp;
  300.     DialogTHndl dt;
  301.  
  302.     dt = (DialogTHndl) GetResource ('DLOG', dialogID);
  303.     HNoPurge ((Handle) dt);
  304.  
  305.     CenterDialog (dt);
  306.  
  307.     dp = GetNewDialog (dialogID, nil, (WindowPtr) -1);
  308.     
  309.     SetArrowCursor ();
  310.     
  311.     ModalDialog (nil, &item);
  312.  
  313.     DisposDialog (dp);
  314.     HPurge ((Handle) dt);
  315.  
  316.     }
  317.  
  318. /*****************************************************************************/
  319.  
  320. /* UserItem to outline the OK button in a dialog box. */
  321.  
  322. static pascal void OutlineOK (DialogPtr dp, short item)
  323.     {
  324.     
  325.     /* BULLSHIT: Do I need to worry about A5 here? */
  326.     
  327.     PenState originalPenState;
  328.  
  329.     Rect r;
  330.     Handle h;
  331.     short itemType;
  332.     
  333.     GetPenState (&originalPenState);
  334.  
  335.     item = ok;
  336.  
  337.     GetDItem (dp, item, &itemType, &h, &r);
  338.  
  339.     PenNormal ();
  340.     PenSize (3, 3);
  341.     
  342.     InsetRect (&r, -4, -4);
  343.     FrameRoundRect (&r, 16, 16);
  344.  
  345.     SetPenState (&originalPenState);
  346.     
  347.     }
  348.  
  349. /*****************************************************************************/
  350.  
  351. void SetOutlineOKHook (DialogPtr dp, short hookItem)
  352.     {
  353.     
  354.     short itemType;
  355.     Rect r;
  356.     Handle h;
  357.  
  358.     GetDItem (dp, hookItem, &itemType, &h                  , &r);
  359.     SetDItem (dp, hookItem,  itemType, (Handle) &OutlineOK, &r);
  360.     
  361.     }
  362.  
  363. /*****************************************************************************/
  364.  
  365. /* UserItem to outline a button group box, except for top text */
  366.  
  367. static pascal void OutlineGroup (DialogPtr dp, short item)
  368.     {
  369.  
  370.     Rect     r, rText;
  371.     Handle     h;
  372.     short     itemType;
  373.     PenState originalPenState;
  374.  
  375.     GetPenState (&originalPenState);
  376.  
  377.     GetDItem (dp, item+1, &itemType, &h, &rText);    /* bounds of surrounding text */
  378.     GetDItem (dp, item,   &itemType, &h, &r);        /* the group box */
  379.     
  380.     PenNormal ();
  381.     PenSize (1, 1);
  382.     
  383.     MoveTo (rText.right, r.top);
  384.     LineTo (r.right, r.top);
  385.     LineTo (r.right, r.bottom);
  386.     LineTo (r.left, r.bottom);
  387.     LineTo (r.left, r.top);
  388.     LineTo (rText.left, r.top);
  389.     
  390.     SetPenState (&originalPenState);
  391.     
  392.     }
  393.  
  394. /*****************************************************************************/
  395.  
  396. /* The following routine sets a user item to be a group box.  It expects
  397.    the next item to be the title for the group box. */
  398.  
  399. void SetOutlineGroup (DialogPtr dp, short groupItem)
  400.     {
  401.     
  402.     short itemType;
  403.     Rect r;
  404.     Handle h;
  405.  
  406.     GetDItem (dp, groupItem, &itemType, &h                     , &r);
  407.     SetDItem (dp, groupItem,  itemType, (Handle) &OutlineGroup, &r);
  408.     
  409.     }
  410.  
  411. /*****************************************************************************/
  412.  
  413. /* The following routine selects an edit text item. */
  414.  
  415. void SelectTextItem (DialogPtr dp, short item)
  416.     {
  417.     
  418.     SelIText (dp, item, 0, 32767);
  419.     
  420.     }
  421.  
  422. /*****************************************************************************/
  423.  
  424. /* The following routine sets the text of a text item. */
  425.  
  426. void StuffText (DialogPtr dp, short item, Str255 text)
  427.     {
  428.     
  429.     Rect r;
  430.     short itemType;
  431.     Handle textHdl;
  432.     
  433.     GetDItem (dp, item, &itemType, &textHdl, &r);
  434.     
  435.     SetIText (textHdl, text);
  436.     
  437.     }
  438.  
  439. /*****************************************************************************/
  440.  
  441. /* The following routine extracts the text of a text item. */
  442.  
  443. void FetchText (DialogPtr dp, short item, Str255 text)
  444.     {
  445.     
  446.     Rect r;
  447.     short itemType;
  448.     Handle textHdl;
  449.     
  450.     GetDItem (dp, item, &itemType, &textHdl, &r);
  451.     
  452.     GetIText (textHdl, text);
  453.     
  454.     }
  455.  
  456. /*****************************************************************************/
  457.  
  458. /* The following routine stuffs a numeric value into a text field. */
  459.  
  460. void StuffNumber (DialogPtr dp, short item, long value)
  461.     {
  462.     
  463.     Str255 s;
  464.         
  465.     NumToString (value, s);
  466.     
  467.     StuffText (dp, item, s);
  468.     
  469.     }
  470.  
  471. /*****************************************************************************/
  472.  
  473. Boolean StringToNumber (Str255 s, long *value)
  474.     {
  475.     
  476.     short i;
  477.     short j;
  478.     long x;
  479.     Boolean negative = FALSE;
  480.     Boolean isNumber = TRUE;
  481.     Boolean trailingBlanks = FALSE;
  482.     
  483.     for (i = 1, j = 0; i <= Length (s) && isNumber; ++i)
  484.         {
  485.         
  486.         if (j == 0 && s [i] == ' ')
  487.             ; /* Do nothing: Leading blanks */
  488.             
  489.         else if (j > 0 && s [i] == ' ')
  490.             trailingBlanks = TRUE;
  491.             
  492.         else if (trailingBlanks && s [i] != ' ')
  493.             isNumber = FALSE;
  494.             
  495.         else if (j == 0 && !negative && s [i] == '-')
  496.             negative = TRUE;
  497.             
  498.         else if (s [i] < '0' || s [i] > '9')
  499.             isNumber = FALSE;
  500.             
  501.         else
  502.             s [++j] = s [i];
  503.         
  504.         }
  505.         
  506.     if (j == 0)
  507.         isNumber = FALSE;
  508.     else
  509.         s [0] = (char) j;
  510.     
  511.     if (isNumber)
  512.         {
  513.         
  514.         if (j <= 9)
  515.             StringToNum (s, &x);
  516.         else
  517.             x = 0x7FFFFFFF;
  518.         
  519.         if (negative)
  520.             x = -x;
  521.             
  522.         *value = x;
  523.             
  524.         }
  525.         
  526.     return isNumber;
  527.     
  528.     }
  529.  
  530. /*****************************************************************************/
  531.  
  532. /* 
  533.    Here is the corresponding routine to retrieve the value from a text
  534.    field.  It will do range checking and validate that it has been
  535.    handed a number.  If it has not been handed a number, it brings up
  536.    an appropriate error dialog, inserts an appropriately pinned value,
  537.    and selects the item.
  538.   
  539.    It returns TRUE iff it gets a valid value in the field. */
  540.  
  541.  Boolean FetchNumber (DialogPtr dp,
  542.                        short item,
  543.                       long min,
  544.                       long max,
  545.                       long *value)
  546.     {
  547.     
  548.     #define badNumberID 16990
  549.     #define outOfRangeID 16991
  550.     
  551.     Str255 s;
  552.     long x;
  553.     Boolean notANumber;
  554.     
  555.     FetchText (dp, item, s);
  556.     
  557.     notANumber = !StringToNumber (s, &x);
  558.     
  559.     if (notANumber || x < min || x > max)
  560.         {
  561.         
  562.         Str255 minText;
  563.         Str255 maxText;
  564.         
  565.         NumToString (min, minText);
  566.         NumToString (max, maxText);
  567.         
  568.         ParamText (minText, maxText, nil, nil);
  569.         
  570.         (void) ShowAlert (notANumber ? badNumberID : outOfRangeID);
  571.                           
  572.         if (!notANumber)
  573.             {
  574.             
  575.             x = (x < min ? min : max);
  576.             
  577.             StuffNumber (dp, item, x);
  578.             
  579.             }
  580.             
  581.         SelectTextItem (dp, item);
  582.             
  583.         return FALSE;
  584.         
  585.         }
  586.     
  587.     else
  588.         {
  589.         
  590.         *value = x;
  591.         
  592.         return TRUE;
  593.         
  594.         }
  595.         
  596.     #undef badNumberID
  597.     #undef outOfRangeID
  598.     
  599.     }
  600.  
  601.  
  602. /*****************************************************************************/
  603.  
  604. /* Set the state of a check box (or radio button). */
  605.  
  606. void SetCheckBoxState (DialogPtr dp, short item, Boolean checkIt)
  607.     {
  608.  
  609.     Rect    r;
  610.     Handle    ctl;
  611.     short    itemType;
  612.     short    oldValue, newValue;
  613.     
  614.     GetDItem (dp, item, &itemType, &ctl, &r);
  615.  
  616.     oldValue =  GetCtlValue ((ControlHandle) ctl);
  617.     
  618.     newValue = checkIt ? 1 : 0;
  619.  
  620.     if (oldValue != newValue)
  621.         SetCtlValue ((ControlHandle) ctl, newValue);
  622.  
  623.     }
  624.  
  625. /*****************************************************************************/
  626.  
  627. /* Determine the state of a check box (or radio button). */
  628.  
  629. Boolean GetCheckBoxState (DialogPtr dp, short item)
  630.     {
  631.     
  632.     Rect    r;
  633.     Handle    ctl;
  634.     short    itemType;
  635.     short    oldValue;
  636.     
  637.     GetDItem (dp, item, &itemType, &ctl, &r);
  638.  
  639.     oldValue = GetCtlValue ((ControlHandle) ctl);
  640.     
  641.     return (oldValue != 0);
  642.     
  643.     }
  644.  
  645. /*****************************************************************************/
  646.  
  647. /* Set a radio group (from first to last item) to reflect the selection. */
  648.  
  649. void SetRadioGroupState (DialogPtr dp,
  650.                          short first,
  651.                          short last,
  652.                          short item)
  653.     {
  654.  
  655.     short            i;
  656.     
  657.     for (i = first; i <= last; ++i)
  658.         SetCheckBoxState (dp, i, i == item);
  659.  
  660.     }
  661.  
  662. /*****************************************************************************/
  663.  
  664. /* Get the selected radio button in a group. */
  665.  
  666. short GetRadioGroupState (DialogPtr dp, short first, short last)
  667.     {
  668.     
  669.     short i;
  670.     
  671.     for (i = first; i <= last; ++i)
  672.         if (GetCheckBoxState (dp, i))
  673.             return i;
  674.             
  675.     return 0;
  676.     
  677.     }
  678.  
  679. /*****************************************************************************/
  680.  
  681. /* Utility routine to disable a control. */
  682.  
  683. void DisableControl (DialogPtr dp, short item)
  684.     {
  685.  
  686.     Rect    r;
  687.     Handle    ctl;
  688.     short    itemType;
  689.     short    oldValue;
  690.     
  691.     GetDItem (dp, item, &itemType, &ctl, &r);
  692.  
  693.     itemType |= itemDisable;
  694.  
  695.     oldValue = GetCtlValue ((ControlHandle) ctl);
  696.     if (oldValue != 0)
  697.         SetCtlValue ((ControlHandle) ctl, 0);
  698.  
  699.     HiliteControl ((ControlHandle) ctl, 255);
  700.  
  701.     SetDItem (dp, item, itemType, ctl, &r);
  702.  
  703.     }
  704.  
  705. /*****************************************************************************/
  706.  
  707. /* Utility routine to enable a control. */
  708.  
  709. void EnableControl (DialogPtr dp, short item)
  710.     {
  711.  
  712.     Rect    r;
  713.     Handle    ctl;
  714.     short    itemType;
  715.     
  716.     GetDItem (dp, item, &itemType, &ctl, &r);
  717.  
  718.     itemType &= ~itemDisable;
  719.  
  720.     HiliteControl ((ControlHandle) ctl, 0);
  721.  
  722.     SetDItem (dp, item, itemType, ctl, &r);
  723.  
  724.     }
  725.  
  726. /*****************************************************************************/
  727.  
  728. /* Utility routine to invalidate an item. */
  729.  
  730. void InvalItem (DialogPtr dp, short item)
  731.     {
  732.     
  733.     Rect    r;
  734.     Handle    h;
  735.     short    itemType;
  736.     GrafPtr oldPort;
  737.     
  738.     GetDItem (dp, item, &itemType, &h, &r);
  739.     
  740.     GetPort (&oldPort);
  741.     
  742.     SetPort (dp);
  743.     
  744.     InvalRect (&r);
  745.     
  746.     SetPort (oldPort);
  747.     
  748.     }
  749.  
  750. /*****************************************************************************/
  751.  
  752. /* Little routine to flash a button set off by a keystroke. */
  753.  
  754. void FlashDialogButton (DialogPtr dp, short item)
  755.     {
  756.  
  757.     short itemType;
  758.     Handle h;
  759.     Rect r;
  760.  
  761.     GetDItem (dp, item, &itemType, &h, &r);
  762.     
  763.     if (itemType == (ctrlItem + btnCtrl))
  764.         {
  765.  
  766.         long ignore;
  767.  
  768.         HiliteControl ((ControlHandle) h, 1);
  769.  
  770.         Delay (5, &ignore);
  771.  
  772.         HiliteControl ((ControlHandle) h, 0);
  773.  
  774.         }
  775.  
  776.     }
  777.  
  778. /*****************************************************************************/
  779.  
  780.